package com.mars.module.tool.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mars.common.base.UserContextInfo;
import com.mars.framework.context.ContextUserInfoThreadHolder;
import com.mars.framework.exception.ServiceException;
import com.mars.module.system.entity.SysRoleMenu;
import com.mars.module.system.mapper.SysRoleMenuMapper;
import com.mars.module.tool.entity.GenSysMenu;
import com.mars.module.tool.mapper.GenSysMenuMapper;
import com.mars.module.tool.request.GenSysMenuRequest;
import com.mars.module.tool.service.ISysMenuGenService;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 功能描述
 *
 * @author Mars.wq [wqexpore@163.com]
 * @version 1.0
 * @date 2023-11-08 17:14:42
 */
@Service
@AllArgsConstructor
public class SysMenuGenServiceImpl implements ISysMenuGenService {

    private final GenSysMenuMapper genSysMenuMapper;

    private final SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveGenMenu(GenSysMenuRequest request, String functionName, String tableName) {
        int menuType = Objects.nonNull(request.getMenuType()) ? request.getMenuType() : 1;
        // 查询该用户角色
        UserContextInfo userContextInfo = ContextUserInfoThreadHolder.get();
        Long roleId = genSysMenuMapper.selectRoleId(userContextInfo.getId());
        // 获取目录
        if (menuType == 1) {
            GenSysMenu dirMenu = new GenSysMenu();
            BeanUtils.copyProperties(request, dirMenu);
            Integer maxSort = selectMaxSort(1, null);
            dirMenu.setSort(maxSort);
            dirMenu.setTableSource(tableName);
            // 保存目录
            genSysMenuMapper.insert(dirMenu);
            saveMenu(request, dirMenu, tableName);
        } else {
            // 根据菜单ID查询菜单
            GenSysMenu sysMenu = genSysMenuMapper.selectOne(Wrappers.lambdaQuery(GenSysMenu.class)
                    .eq(GenSysMenu::getId, request.getParentId()));
            // 保存菜单
            this.saveMenu(request, sysMenu, tableName);
        }
        // 保存角色菜单
        this.saveRoleMenuList(tableName, roleId);

    }

    /**
     * 保存角色菜单
     *
     * @param tableName functionName
     * @param roleId    角色ID
     */
    private void saveRoleMenuList(String tableName, Long roleId) {
        List<GenSysMenu> genSysMenus = genSysMenuMapper.selectMenuListByName(tableName);
        if (CollectionUtils.isNotEmpty(genSysMenus)) {
            List<Long> menuIds = genSysMenus.stream().map(GenSysMenu::getId).collect(Collectors.toList());
            List<SysRoleMenu> sysRoleMenus = menuIds.stream().map(x -> {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(roleId);
                roleMenu.setCreateTime(LocalDateTime.now());
                roleMenu.setMenuId(x);
                return roleMenu;
            }).collect(Collectors.toList());
            sysRoleMenuMapper.insertBatchSomeColumn(sysRoleMenus);
        }
    }

    @Override
    public Integer selectMaxSort(Integer type, Long menuId) {
        if (type == 2) {
            if (Objects.isNull(menuId)) {
                throw new ServiceException("菜单ID不能为空");
            }
        }
        List<GenSysMenu> selectList = genSysMenuMapper.selectList(Wrappers.lambdaQuery(GenSysMenu.class)
                .eq(GenSysMenu::getMenuType, type).eq(Objects.nonNull(menuId), GenSysMenu::getParentId, menuId)
                .orderByDesc(GenSysMenu::getSort));
        if (CollectionUtils.isEmpty(selectList)) {
            return 1;
        } else {
            return selectList.get(0).getSort() + 1;
        }
    }

    @Override
    public List<Long> selectListByMenuName(Integer type, String menuName) {

        return null;
    }

    @Override
    public GenSysMenu selectMenuByName(String menuName) {
        return genSysMenuMapper.selectOne(Wrappers.lambdaQuery(GenSysMenu.class)
                .eq(GenSysMenu::getMenuName, menuName));
    }

    /**
     * 保存菜单
     *
     * @param request   请求参数
     * @param dirMenu   dirMenu
     * @param tableName tableName
     */
    private void saveMenu(GenSysMenuRequest request, GenSysMenu dirMenu, String tableName) {
        if (request.getMenuType() == 1) {
            // 构建菜单
            GenSysMenuRequest menuRequest = request.getChildren().get(0);
            GenSysMenu menu = new GenSysMenu();
            BeanUtils.copyProperties(menuRequest, menu);
            menu.setSort(1);
            menu.setTableSource(tableName);
            menu.setParentId(dirMenu.getId());
            // 保存菜单
            genSysMenuMapper.insert(menu);
            // 保存按钮权限
            List<GenSysMenuRequest> childrenList = menuRequest.getChildren();
            List<GenSysMenu> buttonMenuList = getButtonMenuList(menu, childrenList);
            genSysMenuMapper.insertBatchSomeColumn(buttonMenuList);
        } else {
            GenSysMenu menu = new GenSysMenu();
            BeanUtils.copyProperties(request, menu);
            menu.setParentId(dirMenu.getId());
            menu.setSort(1);
            menu.setTableSource(tableName);
            // 保存菜单
            genSysMenuMapper.insert(menu);
            // 保存按钮权限
            List<GenSysMenuRequest> childrenList = request.getChildren();
            List<GenSysMenu> buttonMenuList = getButtonMenuList(menu, childrenList);
            genSysMenuMapper.insertBatchSomeColumn(buttonMenuList);
        }

    }

    @NotNull
    private List<GenSysMenu> getButtonMenuList(GenSysMenu menu, List<GenSysMenuRequest> childrenList) {
        return childrenList.stream().map(x -> {
            GenSysMenu sysMenu = new GenSysMenu();
            BeanUtils.copyProperties(x, sysMenu);
            sysMenu.setParentId(menu.getId());
            sysMenu.setTableSource(menu.getTableSource());
            sysMenu.setDeleted(0);
            return sysMenu;
        }).collect(Collectors.toList());
    }
}
